package com.yf.customdubbo;

import com.yf.customdubbo.annotation.RpcService;
import com.yf.customdubbo.registry.IServiceRegistryCenter;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

import java.util.HashMap;
import java.util.Map;

public class RpcServer {
    private IServiceRegistryCenter serviceRegistryCenter;
    private String serviceAddress;

    Map<String,Object> handlerMap=new HashMap<String,Object>();

    public RpcServer(IServiceRegistryCenter serviceRegistryCenter,String serviceAddress){
        this.serviceRegistryCenter=serviceRegistryCenter;
        this.serviceAddress=serviceAddress;
    }

    //使用一个方法bind:服务名称--服务对象
    public void bind(Object... services){
        //遍历出传入了多少个服务对象，map.put(serviceName,实现对象)
        for (Object service:services){
            RpcService annotation=service.getClass().getAnnotation(RpcService.class);
            String serviceName=annotation.value().getName();
            handlerMap.put(serviceName,service);

        }
    }

    public void registerAndListen(){
        //1.注册服务地址，先遍历一下handlerMap中有多少服务名称
        for (String serviceName:handlerMap.keySet()){
            //注册服务名称和服务地址
            serviceRegistryCenter.register(serviceName,serviceAddress);
        }

        //2.要监听端口，并且要进行与客户端通信  netty
        try{
            EventLoopGroup bossGroup=new NioEventLoopGroup();
            EventLoopGroup workerGroup=new NioEventLoopGroup();
            //启动netty的服务
            ServerBootstrap bootstrap=new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup);
            bootstrap.channel(NioServerSocketChannel.class);

            bootstrap.childHandler(
                    new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline=socketChannel.pipeline();

                            pipeline.addLast("frameDecoder",new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                            pipeline.addLast("frameEncoder",new LengthFieldPrepender(4));
                            pipeline.addLast("encoder",new ObjectEncoder());
                            pipeline.addLast("decoder",new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
                            pipeline.addLast("handler",new RpcServerHandler(handlerMap));
                        }
                    }
            ).option(ChannelOption.SO_BACKLOG,128).childOption(ChannelOption.SO_KEEPALIVE,true);

            //通过netty监听
            String[] addrs=serviceAddress.split(":");
            String ip=addrs[0];
            int port=Integer.parseInt(addrs[1]);

            ChannelFuture future=bootstrap.bind(ip,port).sync();
            System.out.println("netty 服务端启动成功，等待客户端的连接");
            future.channel().closeFuture().sync();





        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
